package com.tanhua.dubbo.api;

import com.tanhua.domain.mongo.Comment;
import com.tanhua.domain.mongo.Publish;
import com.tanhua.domain.mongo.Video;
import com.tanhua.domain.vo.PageResult;
import org.apache.dubbo.config.annotation.Service;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.util.List;

/**
 * @author anshuai
 * @create 2021-02-01 16:05
 */
@Service
public class CommentApiImpl implements CommentApi {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 增加操作（点赞、评论、喜欢）
     *
     * @param comment Comment信息对象
     * @return
     */
    @Override
    public long save(Comment comment) {
        //1.补全数据
        comment.setId(ObjectId.get());
        comment.setCreated(System.currentTimeMillis());

        //2.储存到mongodb中
        mongoTemplate.save(comment);

        //3. 更新动态的计数：+1。
        // 如果操作类型commentType是1：是点赞，要对publish的likeCount+1
        // 如果操作类型commentType是2：是文字评论，要对publish的commentCount+1
        // 如果操作类型commentType是3：是喜欢，要对publish的loveCount+1
        Query query = new Query(Criteria.where("id").is(comment.getPublishId()));
        //将点赞的赞数加1
        Update update = new Update().inc(getColumnName(comment.getCommentType()), 1);
        FindAndModifyOptions options = new FindAndModifyOptions();
        //  是否修改后获取最新的值
        options.returnNew(true);

        Publish publish = mongoTemplate.findAndModify(query, update, options, Publish.class);

        //返回最新的点赞数
        return getCount(publish,comment.getCommentType());
    }

    /**
     * 对评论点赞
     * @param comment Comment信息对象
     * @return
     */
    @Override
    public long saveComment(Comment comment) {
        //1.补全数据
        comment.setId(ObjectId.get());
        comment.setCreated(System.currentTimeMillis());

        //2.储存到mongodb中
        mongoTemplate.save(comment);

        //3. 更新动态的计数：+1。
        // 如果操作类型commentType是1：是点赞，要对comment的likeCount+1
        Query query = new Query(Criteria.where("id").is(comment.getPublishId()));
        //将点赞的赞数加1
        Update update = new Update().inc(getColumnName(comment.getCommentType()), 1);
        FindAndModifyOptions options = new FindAndModifyOptions();
        //  是否修改后获取最新的值
        options.returnNew(true);

        Comment newComment = mongoTemplate.findAndModify(query, update, options, Comment.class);
        return newComment.getLikeCount();
    }

    /**
     * 对视频点赞
     * @param comment Comment对象
     * @return
     */
    @Override
    public long saveVideo(Comment comment) {
        //1.补全数据
        comment.setId(ObjectId.get());
        comment.setCreated(System.currentTimeMillis());

        //2.储存到mongodb中
        mongoTemplate.save(comment);

        //3. 更新动态的计数：+1。
        // 如果操作类型commentType是1：是点赞，要对comment的likeCount+1
        Query query = new Query(Criteria.where("id").is(comment.getPublishId()));
        //将点赞的赞数加1
        Update update = new Update().inc(getColumnName(comment.getCommentType()), 1);
        FindAndModifyOptions options = new FindAndModifyOptions();
        //  是否修改后获取最新的值
        options.returnNew(true);

        Video video = mongoTemplate.findAndModify(query, update, options, Video.class);
        return video.getLikeCount();
    }

    /**
     * 取消操作（取消点赞、取消评论、取消喜欢）
     *
     * @param comment Comment信息对象
     * @return
     */
    @Override
    public long remove(Comment comment) {
        //1. 删除之前的评论数据{userId: 124, publishId: xxxx, commentType: 1}
        Criteria criteria = Criteria.where("userId").is(comment.getUserId())
                .and("publishId").is(comment.getPublishId())
                .and("commentType").is(comment.getCommentType());
        mongoTemplate.remove(new Query(criteria),Comment.class);

        //2. 更新计数：-1
        Query query = new Query(Criteria.where("id").is(comment.getPublishId()));
        Update update = new Update().inc(getColumnName(comment.getCommentType()),-1);
        FindAndModifyOptions options = new FindAndModifyOptions();
        options.returnNew(true);

        Publish publish = mongoTemplate.findAndModify(query, update, options, Publish.class);
        //3. 获取并返回最新计数
        return getCount(publish,comment.getCommentType());
    }

    /**
     * 评论-取消点赞
     * @param comment Comment信息对象
     * @return 最新的点赞数
     */
    @Override
    public long removeComment(Comment comment) {
        //1.删除之前的评论数据(删除的是某用户点赞的记录)
        Criteria criteria = Criteria.where("userId").is(comment.getUserId())
                .and("publishId").is(comment.getPublishId())
                .and("commentType").is(comment.getCommentType());
        mongoTemplate.remove(new Query(criteria),Comment.class);

        //2.更新计数(更新的评论用户的评论数据的点赞数)
        Query query = new Query(Criteria.where("id").is(comment.getPublishId()));
        Update update = new Update().inc(getColumnName(comment.getCommentType()), -1);
        FindAndModifyOptions options = new FindAndModifyOptions();
        options.returnNew(true);

        Comment newComment = mongoTemplate.findAndModify(query, update, options, Comment.class);
        return newComment.getLikeCount();
    }

    /**
     * 视频-取消点赞
     * @param comment Comment信息对象
     * @return
     */
    @Override
    public long removeVideo(Comment comment) {
        //1.删除之前的评论数据(删除的是某用户点赞的记录)
        Criteria criteria = Criteria.where("userId").is(comment.getUserId())
                .and("publishId").is(comment.getPublishId())
                .and("commentType").is(comment.getCommentType());
        mongoTemplate.remove(new Query(criteria),Comment.class);

        //2.更新计数(更新的评论用户的评论数据的点赞数)
        Query query = new Query(Criteria.where("id").is(comment.getPublishId()));
        Update update = new Update().inc(getColumnName(comment.getCommentType()), -1);
        FindAndModifyOptions options = new FindAndModifyOptions();
        options.returnNew(true);

        Video video = mongoTemplate.findAndModify(query, update, options, Video.class);
        return video.getLikeCount();
    }

    /**
     * 分页查询某一动态的文字评论列表
     * @param movementId 动态id
     * @param page 页码
     * @param pagesize 查询几条
     * @return
     */
    @Override
    public PageResult<Comment> findCommentList(String movementId, int page, int pagesize) {
        //创建查询条件
        Criteria criteria = Criteria.where("publishId").is(new ObjectId(movementId))
                .and("commentType").is(2);

        //对查询结果做排序
        Query query = new Query(criteria)
                .with(Sort.by(Sort.Order.desc("likeCount"), Sort.Order.desc("created")))
                .with(PageRequest.of(page - 1, pagesize));

        //执行查询出评论列表
        List<Comment> commentList = mongoTemplate.find(query, Comment.class);
        //计算总数量
        long count = mongoTemplate.count(query, Comment.class);

        //计算分了多少页
        int pages = (int) Math.ceil(count * 1.0 / pagesize);
        //返回评论列表分页对象
        return new PageResult<>((int)count,pagesize,pages,page,commentList);
    }

    /**
     * 分页查询针对某一用户的评论列表
     * @param userId 用户id
     * @param commentType 评论类型
     * @param page 页码
     * @param pagesize 每页几条
     * @return
     */
    @Override
    public PageResult<Comment> findCommentsByUser(Long userId, int commentType, int page, int pagesize) {
        Criteria criteria = Criteria.where("publishUserId").is(userId).and("commentType").is(commentType);
        Query query = new Query(criteria)
                .with(Sort.by(Sort.Order.desc("created")))
                .with(PageRequest.of(page-1,pagesize));

        List<Comment> commentList = mongoTemplate.find(query, Comment.class);
        long count = mongoTemplate.count(query, Comment.class);
        int pages = (int) Math.ceil(count * 1.0 / pagesize);
        return new PageResult<>((int)count,pagesize,pages,page,commentList);
    }

    /**
     * 查询一条动态的评论
     * @param commentId 评论id
     * @return
     */
    @Override
    public Comment findById(String commentId) {
        return mongoTemplate.findById(new ObjectId(commentId),Comment.class);
    }

    /**
     * 根据操作类型，获取要操作的字段名称
     * @param commentType 操作类型。1点赞，2评论，3喜欢
     * @return 操作类型对应的字段名
     */
    private String getColumnName(Integer commentType) {
        if (commentType == 1) {
            return "likeCount";
        } else if (commentType == 2) {
            return "commentCount";
        } else if (commentType == 3) {
            return "loveCount";
        }

        return "";
    }

    /**
     * 根据操作类型，从Publish中获取相应的计数
     * @param publish 动态信息publish
     * @param commentType 操作类型（1点赞，2评论，3喜欢）
     * @return commentType相应的计数
     */
    private long getCount(Publish publish, Integer commentType) {
        if (commentType == 1) {
            //点赞了，要获取最新的点赞数
            return publish.getLikeCount();
        } else if (commentType == 2) {
            //文字评论了，要获取最新的文字评论数
            return publish.getCommentCount();
        } else if (commentType == 3) {
            //喜欢了，要获取最新的喜欢数
            return publish.getLoveCount();
        }

        return 0;
    }
}
